package com.product.statemachine.common;

import com.product.statemachine.common.event.StateEvent;
import com.product.statemachine.common.exception.StateMachineException;
import com.product.statemachine.common.executor.DomainStateEventExecutor;
import com.product.statemachine.common.state.State;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;

/**
 * @author caoxingming
 * @name DomainStateMachineFactory
 * @data 2022-08-29-11:14 AM
 * @description: 领域状态机工厂类
 */
@Component
public class DomainStateMachineFactory {

    private HashMap<String,DomainStateMachine> domainStateMachineHashMap = new HashMap<>(10);


    /***
     * 获取领域状态机对象
     * @param domainStateMachineName
     * @return
     */
    public DomainStateMachine getDomainStateMachineBean(String domainStateMachineName) {
        Optional.ofNullable(domainStateMachineName).<StateMachineException>orElseThrow(()->{ throw new StateMachineException(domainStateMachineName+"不能为空"); });
        DomainStateMachine machine = domainStateMachineHashMap.get(domainStateMachineName);
        Optional.ofNullable(machine).<StateMachineException>orElseThrow(()->{ throw new StateMachineException("不存在状态机"+domainStateMachineName); });
        return domainStateMachineHashMap.get(domainStateMachineName);
    }


    /***
     * 初始化工厂对象
     */
    public void initFactory() {
        List<String> domainStateMachineNamesInOperate = domainStateMachineEnvironment.getDomainStateMachineNamesInOperate();
        HashMap<String, HashMap<String, StateEvent>> stateEventMapWithDomainStateMachineName = domainStateMachineEnvironment.getStateEventHashMap();
        HashMap<String, HashMap<String, DomainStateEventExecutor>> domainStateEventExecutorMapWithDomainStateMachineName = domainStateMachineEnvironment.getDomainStateEventExecutors();
        HashMap<String, HashMap<String, State>> stateMapWithDomainStateMachineName = domainStateMachineEnvironment.getStateHashMap();
        if(CollectionUtils.isEmpty(domainStateMachineNamesInOperate)) {
            return;
        }
        domainStateMachineNamesInOperate.stream().forEach(domainStateMachineName-> {
            HashMap<String, StateEvent> stateEventMap = stateEventMapWithDomainStateMachineName.get(domainStateMachineName);
            HashMap<String, DomainStateEventExecutor> domainStateEventExecutorMap = domainStateEventExecutorMapWithDomainStateMachineName.get(domainStateMachineName);
            HashMap<String, State> stateHashMap = stateMapWithDomainStateMachineName.get(domainStateMachineName);
            if(CollectionUtils.isEmpty(stateEventMap) || CollectionUtils.isEmpty(domainStateEventExecutorMap) || CollectionUtils.isEmpty(stateHashMap)) {
                return;
            }
            DomainStateMachine domainStateMachine = new DomainStateMachine(domainStateMachineName,stateHashMap,stateEventMap,domainStateEventExecutorMap);
            domainStateMachineHashMap.put(domainStateMachineName,domainStateMachine);
        });

    }

    @Resource
    private DomainStateMachineEnvironment domainStateMachineEnvironment;



}
